import { Cfetch, interceptors } from './OriginFetch';
import { merge } from 'lodash';
import { message } from 'antd';

export interface customRequestInit extends RequestInit {
  showError?: boolean;
  canEmpty?: boolean;
  returnOrigin?: boolean;
  withoutCheck?: boolean;
  timeout?: number;
  responseType?: 'json' | 'text' | 'blob';
  prefix?: string;
}
/**
 * config 自定义配置项
 * @param withoutCheck 不使用默认的接口状态校验，直接返回 response
 * @param returnOrigin 是否返回整个 response 对象，为 false 只返回 response.data
 * @param showError 全局错误时，是否使用统一的报错方式
 * @param canEmpty 传输参数是否可以为空
 * @param mock 是否使用 mock 服务
 * @param timeout 接口请求超时时间，默认10秒
 * @param prefix url 前缀
 */
let configDefault: customRequestInit = {
  showError: true,
  canEmpty: false,
  returnOrigin: false,
  withoutCheck: false,
  timeout: 10000,
  responseType: 'json',
  prefix: process.env.NODE_ENV === 'production' ? 'http://110.42.168.32:8080' : '/api',
};

// 添加请求拦截器
interceptors.request.use((config: any) => {
  // 这里是我项目使用到的js-cookie库，主要是为了拿到token，你们这里改成你们获取token的方式即可
  const token = localStorage.getItem('token');
  const mergeConfig = merge(
    {
      responseType: 'json',
      headers: {
        'Content-Type': 'application/json;charset=utf-8',
      },
    },
    configDefault,
    config
  );

  mergeConfig.headers['Authorization'] = token && token !== null ? token : '';

  return mergeConfig;
});

// 添加响应拦截器
interceptors.response.use(async (response: Response, config: customRequestInit) => {
  // HTTP 状态码 2xx 状态入口，data.code 为 200 表示数据正确，无任何错误
  if (response.status >= 200 && response.status < 300) {
    const json = await resultReduction(response.clone(), config);
    if (config.responseType === 'json' && json && json.code) {
      if (json.code === 401) {
        localStorage.removeItem('token');
        location.reload();
      }

      if (json.code === 500) {
        message.error(json.msg);
      }
    }
    return Promise.resolve(json);
  } else {
    // 非 2xx 状态入口
    if (configDefault.withoutCheck) {
      // 不进行状态状态检测
      return Promise.reject(response);
    }
    return Promise.reject(response);
  }
});

// 结果处理，fetch请求响应结果是promise，还得处理
async function resultReduction(response: Response, config?: customRequestInit) {
  let res: any | Promise<any> = '';
  switch (config.responseType) {
    case 'json':
      res = await response.json();
      break;
    case 'text':
      res = await response.text();
      break;
    case 'blob':
      res = await response.blob();
      break;
    default:
      res = await response.json();
      break;
  }
  return res;
}

function request(method: string, path: RequestInfo, data: any, config: customRequestInit) {
  const { prefix } = configDefault;
  let myInit = {
    method,
    ...configDefault,
    ...config,
    body: JSON.stringify(data),
  };
  if (method === 'GET') {
    let params = '';
    if (data) {
      // 对象转url参数
      params = JSON.stringify(data)
        .replace(/:/g, '=')
        .replace(/"/g, '')
        .replace(/,/g, '&')
        .match(/\{([^)]*)\}/)[1];
    }
    return Cfetch(`${prefix}${path}?${params}`, {
      ...configDefault,
      ...config,
    });
  }

  return Cfetch(`${prefix}${path}`, myInit);
}

// get请求方法使用封装
function get(path: string, data?: Record<string, any>, config?: customRequestInit) {
  return request('GET', path, data, config);
}

// post请求方法使用封装
function post(path: string, data?: Record<string, any>, config?: customRequestInit) {
  return request('POST', path, data, config);
}

// put请求方法使用封装
function put(path: string, data?: Record<string, any>, config?: customRequestInit) {
  return request('PUT', path, data, config);
}

// delete请求方法使用封装
function del(path: string, data?: Record<string, any>, config?: customRequestInit) {
  return request('DELETE', path, data, config);
}

export default {
  get,
  post,
  delete: del,
  put,
};
